import { assign } from 'min-dash';

import { Modal } from 'antd';

import { MenuMap } from '../CustomPalette/consts';

import './index.scss';

export default function ContextPadProvider(
  config,
  injector,
  eventBus,
  contextPad,
  modeling,
  elementFactory,
  connect,
  create,
  popupMenu,
  canvas,
  rules,
  translate
) {
  config = config || {};

  this.modeling = modeling;
  this.elementFactory = elementFactory;
  this.connect = connect;
  this.create = create;
  this.translate = translate;
  this.popupMenu = popupMenu;
  this.canvas = canvas;
  this.contextPad = contextPad;

  if (config.autoPlace !== false) {
    this.autoPlace = injector.get('autoPlace', false);
  }

  contextPad.registerProvider(this);
}

ContextPadProvider.$inject = [
  'config.contextPad',
  'injector',
  'eventBus',
  'contextPad',
  'modeling',
  'elementFactory',
  'connect',
  'create',
  'popupMenu',
  'canvas',
  'rules',
  'translate',
];

ContextPadProvider.prototype.getContextPadEntries = function (element) {
  const { canvas, contextPad, autoPlace, create, elementFactory, translate, modeling, connect, popupMenu } = this;

  const getReplaceMenuPosition = (element) => {
    const Y_OFFSET = 5;

    const diagramContainer = canvas.getContainer(),
      pad = contextPad.getPad(element).html;

    const diagramRect = diagramContainer.getBoundingClientRect(),
      padRect = pad.getBoundingClientRect();

    const top = padRect.top - diagramRect.top;
    const left = padRect.left - diagramRect.left;

    const pos = {
      x: left,
      y: top + padRect.height + Y_OFFSET,
    };

    return pos;
  };

  const appendItem = (type, opts = {}) => {
    const { group, className, title, businessObject: options = {} } = {
      ...opts,
      ...(MenuMap[type] || {}),
    };

    const titleStr = title || translate(`Create ${type}`);

    const createShape = () => {
      const shape = elementFactory.createShape(assign({ type: type }, options));
      assign(shape.businessObject, options, { name: titleStr });
      shape.businessObject.di.isExpanded = options.isExpanded;

      return shape;
    };

    const appendStart = (event, element) => {
      const shape = createShape();
      create.start(event, shape, { source: element });
    };

    const append = !autoPlace
      ? appendStart
      : (event, element) => {
          const shape = createShape();
          autoPlace.append(element, shape);
        };

    return {
      group,
      className: className,
      title: title,
      action: {
        dragstart: appendStart,
        click: append,
      },
    };
  };

  const startConnect = (event, element) => {
    connect.start(event, element);
  };

  const removeElement = (e) => {
    modeling.removeElements([element]);
  };

  const actions = {};

  if (
    element.type === 'bpmn:StartEvent' ||
    element.type === 'bpmn:UserTask' ||
    element.type === 'bpmn:ServiceTask' ||
    element.type === 'bpmn:ScriptTask' ||
    element.type === 'bpmn:InvokeTask' ||
    element.type === 'bpmn:ExclusiveGateway' ||
    element.type === 'bpmn:ParallelGateway' ||
    element.type === 'bpmn:IntermediateCatchEvent' ||
    element.type === 'bpmn:IntermediateThrowEvent'
  ) {
    assign(actions, {
      'append.user-task': appendItem('bpmn:UserTask'),
      'append.service-task': appendItem('bpmn:ServiceTask'),
      'append.script-task': appendItem('bpmn:ScriptTask'),
      'append.invoke-task': appendItem('bpmn:InvokeTask'),
      'append.exclusive-gateway': appendItem('bpmn:ExclusiveGateway'),
      'append.parallel-gateway': appendItem('bpmn:ParallelGateway'),
      'append.inclusive-gateway': appendItem('bpmn:InclusiveGateway'),
      'append.timer-intermediate-event': appendItem('bpmn:IntermediateTimerEvent'),
      'append.end-event': appendItem('bpmn:EndEvent'),
      connect: {
        group: 'edit',
        className: 'bpmn-icon-connection-multi',
        title: translate('Connect using DataInputAssociation'),
        action: {
          click: startConnect,
          dragstart: startConnect,
        },
      },
    });
  }

  if (element.type === 'bpmn:Lane' || element.type === 'bpmn:Participant') {
    assign(actions, {
      'lane-insert-above': {
        group: 'lane-insert-above',
        className: 'bpmn-icon-lane-insert-above',
        title: translate('Add Lane above'),
        action: {
          click: function (event, element) {
            modeling.addLane(element, 'top');
          },
        },
      },
      'lane-insert-below': {
        group: 'lane-insert-below',
        className: 'bpmn-icon-lane-insert-below',
        title: translate('Add Lane below'),
        action: {
          click: function (event, element) {
            modeling.addLane(element, 'bottom');
          },
        },
      },
    });
  }

  // 增加替换元素功能
  if (!popupMenu.isEmpty(element, 'bpmn-replace')) {
    assign(actions, {
      replace: {
        group: 'edit',
        className: 'bpmn-icon-screw-wrench',
        title: translate('Change type'),
        action: {
          click: function (event, element) {
            var position = assign(getReplaceMenuPosition(element), {
              cursor: { x: event.x, y: event.y },
            });

            popupMenu.open(element, 'bpmn-replace', position);
          },
        },
      },
    });
  }

  // 删除
  assign(actions, {
    delete: {
      group: 'edit',
      className: 'bpmn-icon-trash',
      title: translate('Remove'),
      action: {
        click: () => {
          Modal.confirm({
            title: '确认删除该元素吗?',
            // icon: <ExclamationCircleOutlined />,
            // content: '',
            okText: '确认',
            cancelText: '取消',
            onOk: () => {
              removeElement();
              Modal.destroyAll()
            },
          });
        },
      },
    },
  });

  // 添加注释
  if (element.type !== 'bpmn:TextAnnotation') {
    assign(actions, {
      'append.text-annotation': appendItem('bpmn:TextAnnotation'),
    });
  }

  return actions;
};
